package com.starryx.blog.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.starryx.blog.NotFoundException;
import com.starryx.blog.dao.BlogMapper;
import com.starryx.blog.po.Blog;
import com.starryx.blog.util.MarkdownUtils;
import com.starryx.blog.util.MyBeanUtils;
import com.starryx.blog.util.RedisUtils;
import com.starryx.blog.vo.BlogQuery;
import com.starryx.blog.vo.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.*;

@Service
public class BlogServiceImpl implements BlogService {

    @Autowired
    private BlogMapper blogMapper;

    @Autowired
    private RedisUtils redisUtils;


    @Override
    public Blog getBlog(Long id) {
        return blogMapper.findOneById(id);
    }

    @Override
    public Blog getAndConvert(Long id) {
        Blog blog = blogMapper.findOneById(id);
        if(blog == null){
            throw new NotFoundException("该博客不存在");
        }
        Blog b = new Blog();        // 在数据库中保存 md 格式，在页面中展示 html ， 所以新建一个临时对象
        BeanUtils.copyProperties(blog, b);
        String content = blog.getContent();
        b.setContent(MarkdownUtils.markdownToHtmlExtensions(content));
        b.setViews(redisUtils.incr("view:article:" + b.getId(), 1L));
        return b;
    }

    @Override
    public PageInfo<Blog> listBlog(Page page, BlogQuery blogQuery) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize(), page.getOrderBy());
        return new PageInfo<Blog>(blogMapper.findAllByBlogQuery(blogQuery));
    }

    @Override
    public PageInfo<Blog> listBlog(Page page) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize(), page.getOrderBy());
        return new PageInfo<Blog>(blogMapper.findAll());
    }

    @Override
    public PageInfo<Blog> listBlog(Long tagId, Page page) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize(), page.getOrderBy());
        return new PageInfo<Blog>(blogMapper.findAllByTagId(tagId));
    }

    @Override
    public List<Blog> listRecommendBlogTop(Integer size) {
        PageHelper.startPage(1, size, "update_time desc");
        PageInfo<Blog> pageInfo = new PageInfo<Blog>(blogMapper.findTop());
        return pageInfo.getList();
    }

    @Override
    public PageInfo<Blog> listBlog(String query, Page page) {
        PageHelper.startPage(page.getPageNum(), page.getPageSize(), page.getOrderBy());
        return new PageInfo<Blog>(blogMapper.findByQuery(query));
    }

    @Override
    public Map<String, List<Blog>> archiveBlog() {
        List<String> years = blogMapper.findGroupYear();
        Map<String, List<Blog>> map = new LinkedHashMap<>();
        for (String year : years){
            map.put(year, blogMapper.findByYear(year));
        }
        return map;
    }

    @Override
    public Long countBlog() {
        return blogMapper.count();
    }

    @Override
    @Transactional
    public int saveBlog(Blog blog) {
        // 这里是将新增和修改放在一起的写法，所以下面的 updateBlog() 是没有用到的，问题不大，分开的写法可参照 TypeService 以及其 Controller 的写法
        if(blog.getId() == null){   // 说明是新增
            blog.setCreateTime(new Date());
            blog.setUpdateTime(new Date());
            blog.setViews(0L);           // 初始化浏览次数为 0
            blog.setFlag("原创");       // 设定默认值，如果不设定，在前端页面没有点选的情况下，是不会有值的
        }else{
            blog.setUpdateTime(new Date());
        }
        return blogMapper.save(blog) == 0 ? 0 :  blogMapper.saveTags(blog);
    }

    @Override
    @Transactional
    public int updateBlog(Long id, Blog blog) {
        Blog b = blogMapper.findOneById(id);
        if (b == null) {
            throw new NotFoundException("该博客不存在");
        }
        BeanUtils.copyProperties(blog, b, MyBeanUtils.getNullPropertNames(blog));      // 将 blog 的各个属性值赋给 b ， 并把属性值为空的属性过滤调
        b.setUpdateTime(new Date());                // 更新修改时间
        blogMapper.deleteTags(b.getId());
        return blogMapper.update(b) == 0 ? 0 : blogMapper.saveTags(b);
    }

    @Override
    @Transactional
    public void deleteBlog(Long id) {
        blogMapper.deleteTags(id);
        blogMapper.delete(id);
    }
}
